/**
过滤器模式（Filter Pattern）

允许开发人员使用不同的标准来过滤一组对象，通过逻辑运算以解耦的方式把它们连接起来。
这种类型的设计模式属于结构型模式，它结合多个标准来获得单一标准。
*/
main(List<String> args) {
  List<Person> persons = List<Person>();

  persons.add(Person("Robert", "Male", "Single"));
  persons.add(Person("John", "Male", "Married"));
  persons.add(Person("Laura", "Female", "Married"));
  persons.add(Person("Diana", "Female", "Single"));
  persons.add(Person("Mike", "Male", "Single"));
  persons.add(Person("Bobby", "Male", "Single"));

  Filter male = MaleFilter();
  Filter female = FemaleFilter();
  Filter single = SingleFilter();
  Filter singleMale = AndFilter(single, male);
  Filter singleOrFemale = OrFilter(single, female);

  print("Males: ");
  male.filter(persons).forEach((p) => print(p));

  print("\nFemales: ");
  female.filter(persons).forEach((p) => print(p));

  print("\nSingle Males: ");
  singleMale.filter(persons).forEach((p) => print(p));

  print("\nSingle Or Females: ");
  singleOrFemale.filter(persons).forEach((p) => print(p));
}

//////////////////////////////////////////////////////////////////

///
/// 创建一个类，在该类上应用过滤器
///
class Person {
  String name;
  String gender;
  String maritalStatus;

  Person(this.name, this.gender, this.maritalStatus);

  @override
  String toString() {
    return 'Person[name="$name", gender="$gender", maritalStatus="$maritalStatus"]';
  }
}

///
/// 创建一个过滤器接口
///
abstract class Filter {
  List<Person> filter(List<Person> persons);
}

///
/// 创建实现了 Filter 接口的实体类
///
class MaleFilter implements Filter {
  @override
  List<Person> filter(List<Person> persons) {
    List<Person> personList = List<Person>();
    for (Person person in persons) {
      if (person.gender.toUpperCase() == "MALE") {
        personList.add(person);
      }
    }
    return personList;
  }
}

class FemaleFilter implements Filter {
  @override
  List<Person> filter(List<Person> persons) {
    List<Person> personList = List<Person>();
    for (Person person in persons) {
      if (person.gender.toUpperCase() == "FEMALE") {
        personList.add(person);
      }
    }
    return personList;
  }
}

class SingleFilter implements Filter {
  @override
  List<Person> filter(List<Person> persons) {
    List<Person> personList = List<Person>();
    for (Person person in persons) {
      if (person.maritalStatus.toUpperCase() == "SINGLE") {
        personList.add(person);
      }
    }
    return personList;
  }
}

class AndFilter implements Filter {
  Filter _filter1;
  Filter _filter2;

  AndFilter(this._filter1, this._filter2);

  @override
  List<Person> filter(List<Person> persons) {
    List<Person> personList = _filter1.filter(persons);
    return _filter2.filter(personList);
  }
}

class OrFilter implements Filter {
  Filter _filter1;
  Filter _filter2;

  OrFilter(this._filter1, this._filter2);

  @override
  List<Person> filter(List<Person> persons) {
    List<Person> personList1 = _filter1.filter(persons);
    List<Person> personList2 = _filter1.filter(persons);

    for (Person person in personList2) {
      if (!personList1.contains(person)) {
        personList1.add(person);
      }
    }
    return personList1;
  }
}
